package cn.fintecher.gis.service;

import cn.fintecher.gis.entity.*;
import cn.fintecher.gis.enums.*;
import cn.fintecher.gis.exception.BadRequestException;
import cn.fintecher.gis.model.WebSocketMessageModel;
import cn.fintecher.gis.model.request.*;
import cn.fintecher.gis.model.response.*;
import cn.fintecher.gis.model.session.SessionModel;
import cn.fintecher.gis.respository.OperatorRepository;
import cn.fintecher.gis.respository.PatrolFileRepository;
import cn.fintecher.gis.respository.PatrolInfoRepository;
import cn.fintecher.gis.respository.PatrolTrackRepository;
import cn.fintecher.gis.utils.BeanUtils;
import cn.fintecher.gis.utils.DateUtil;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.modelmapper.ModelMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("patrolInfoService")
public class PatrolInfoService {

    private final Logger logger = LoggerFactory.getLogger(PatrolInfoService.class);

    @Autowired
    private PatrolInfoRepository patrolInfoRepository;

    @Autowired
    private OperatorRepository operatorRepository;

    @Autowired
    private UploadFileService uploadFileService;

    @Autowired
    private WebSocketService webSocketService;

    @Autowired
    private PatrolTrackRepository patrolTrackRepository;

    @Autowired
    private PatrolFileRepository patrolFileRepository;

    @Autowired
    private LogInfoService logInfoService;

    @Autowired
    private ModelMapper modelMapper;

    /**
     * 维护巡查信息
     *
     * @param request
     * @param sessionModel
     */
    public void createPatrolInfo(PatrolInfoRequest request, SessionModel sessionModel) throws Exception {
        PatrolInfo patrolInfo = new PatrolInfo();
        BeanUtils.copyPropertiesIgnoreNull(request, patrolInfo);
        patrolInfo.setStatus(PatrolStatus.PENDING_PATROL);
        LocalDate localDate = LocalDate.parse(request.getPlanTime(), DateTimeFormat.forPattern("yyyy-MM-dd"));
        patrolInfo.setPlanTime(localDate.toDate());
        patrolInfo.setCreateTime(new Date());
        if (sessionModel.getId().equals(request.getUserId())) {
            logger.error("指派的巡查人不能是本人");
            throw new BadRequestException("patrolInfoController", "designator.can.not.be.himself");
        }
        operatorRepository.findById(request.getUserId()).ifPresent(operator -> {
            patrolInfo.setOperator(operator);
            return;
        });

        operatorRepository.findById(sessionModel.getId()).ifPresent(operator -> {
            patrolInfo.setCreateOperator(operator);
            return;
        });
        patrolInfoRepository.save(patrolInfo);
        WebSocketMessageModel model = new WebSocketMessageModel();
        model.setContent(patrolInfo.getOperator().getUsername() + ":你有一条外业任务需巡查！");
        model.setTitle("外业巡查");
        model.setMsgDate(new Date());
        model.setMessageType(MessageType.PATROL);
        webSocketService.sendMessage(patrolInfo.getOperator().getUsername(), model);
    }

    /**
     * 删除巡查信息
     *
     * @param id
     */
    public void deletePatrolInfoById(String id) {
        patrolInfoRepository.findById(id).ifPresent(patrolInfo -> {
            if (patrolInfo.getStatus().equals(PatrolStatus.PENDING_PATROL)) {//待巡查
                logInfoService.addLog("PatrolInfoController", "deletePatrolInfoById",
                        "id=" + id, "删除的巡查任务是：" + patrolInfo.getName());
                patrolInfoRepository.delete(patrolInfo);
            }
            return;
        });

    }

    /**
     * 查询巡查信息
     *
     * @param pageable
     * @return
     */
    public Page<PatrolInfoResponse> queryPatrolInfoAll(QueryPatrolInfoRequest request, SessionModel sessionModel, Pageable pageable) {
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
//        if (Objects.nonNull(sessionModel)) {
//            builder.and(qPatrolInfo.operator.id.eq(sessionModel.getId()));
//        }
        if (Objects.nonNull(request.getType())) { //巡查类型查询
            builder.and(qPatrolInfo.type.eq(request.getType()));
        }
        DateTime dateTime = new DateTime(DateUtil.getNowDate());
        Date old = dateTime.minusDays(15).toDate();
        if (Objects.equals(request.getIsArchive(), 0)) { //未归档
            builder.and(qPatrolInfo.planTime.gt(old));
            if (Objects.nonNull(request.getStatus())) {
                if (request.getStatus().equals(PatrolStatus.PENDING_PATROL)) {
                    builder.and(qPatrolInfo.status.eq(PatrolStatus.PENDING_PATROL));
                } else {
                    builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
                }
            }
        } else { //已归档
            builder.and(qPatrolInfo.planTime.loe(old));
        }
        Page<PatrolInfo> result = patrolInfoRepository.findAll(builder, pageable);
        Page<PatrolInfoResponse> page = result.map(patrolInfo -> {
            PatrolInfoResponse response = new PatrolInfoResponse();
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo,response);
            if (Objects.nonNull(patrolInfo.getOperator())) {
                response.setUserId(patrolInfo.getOperator().getId());
                response.setUserName(patrolInfo.getOperator().getUsername());
            }
            response.setShow(CommonShow.NO);
            Iterator<PatrolTrack> iterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(patrolInfo.getId())).iterator();
            if(iterator.hasNext()){
                response.setShow(CommonShow.YES);
            }
           return response;
        });
        return page;
    }


    public Page<PatrolInfoResponse> queryPatrolInfoList(QueryPatrolInfoRequest request, Pageable pageable) {
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        if (Objects.nonNull(request.getType())) { //巡查类型查询
            builder.and(qPatrolInfo.type.eq(request.getType()));
        }
        DateTime dateTime = new DateTime(DateUtil.getNowDate());
        Date old = dateTime.minusDays(15).toDate();
//        if (Objects.equals(request.getIsArchive(), 0)) { //未归档
//            builder.and(qPatrolInfo.planTime.gt(old));
//        } else { //已归档
//            builder.and(qPatrolInfo.planTime.loe(old));
//        }
        if (Objects.nonNull(request.getStatus())) {
            if (request.getStatus().equals(PatrolStatus.PENDING_PATROL)) {
                builder.and(qPatrolInfo.status.eq(PatrolStatus.PENDING_PATROL));
            } else {
                builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
            }
        }
        Page<PatrolInfo> result = patrolInfoRepository.findAll(builder, pageable);
        Page<PatrolInfoResponse> page = result.map(patrolInfo -> {
            PatrolInfoResponse response = new PatrolInfoResponse();
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            if (Objects.nonNull(patrolInfo.getOperator())) {
                response.setUserId(patrolInfo.getOperator().getId());
                response.setUserName(patrolInfo.getOperator().getUsername());
            }
            response.setShow(CommonShow.NO);
            Iterator<PatrolTrack> iterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(patrolInfo.getId())).iterator();
            if (iterator.hasNext()) {
                response.setShow(CommonShow.YES);
            }
            return response;
        });
        return page;
    }

    /**
     * 查询已经巡查的结果
     *
     * @param type
     * @param pageable
     * @return
     */
    public Page<PatrolInfoResponse> queryPatrolInfo(PatrolType type, Pageable pageable) {
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
        if (Objects.nonNull(type)) { //巡查类型查询
            builder.and(qPatrolInfo.type.eq(type));
        }
        Page<PatrolInfo> result = patrolInfoRepository.findAll(builder, pageable);
        Page<PatrolInfoResponse> page = result.map(patrolInfo -> {
            PatrolInfoResponse response = new PatrolInfoResponse();
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            response.setShow(CommonShow.NO);
            response.setUserId(patrolInfo.getOperator().getId());
            response.setUserName(patrolInfo.getOperator().getUsername());
            Iterator<PatrolTrack> iterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(patrolInfo.getId())).iterator();
            if (iterator.hasNext()) {
                response.setShow(CommonShow.YES);
            }
            return response;
        });
        return page;
    }

    /**
     * 查询巡查信息(已巡查并归档)
     *
     * @return
     */
    public List<PatrolInfoResponse> getPatrolInfos() {
        List<PatrolInfoResponse> list = new ArrayList<>();
        DateTime dateTime = new DateTime(DateUtil.getNowDate());
        Date old = dateTime.minusDays(15).toDate();
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        builder.and(qPatrolInfo.planTime.loe(old));
        builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Iterator<PatrolInfo> iterator = patrolInfoRepository.findAll(builder,sort).iterator();
        while (iterator.hasNext()) {
            PatrolInfo patrolInfo = iterator.next();
            PatrolInfoResponse response = new PatrolInfoResponse();
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            response.setShow(CommonShow.NO);
            response.setUserId(patrolInfo.getOperator().getId());
            response.setUserName(patrolInfo.getOperator().getUsername());
            Iterator<PatrolTrack> trackIterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(patrolInfo.getId())).iterator();
            if (trackIterator.hasNext()) {
                response.setShow(CommonShow.YES);
            }
            list.add(response);
        }
        return list;
    }


    /**
     * app查询接口
     *
     * @param request
     * @param sessionModel
     * @param pageable
     * @return
     */
    public Page<PatrolAppResponse> queryPatrolInfoApp(QueryPatrolInfoRequest request, SessionModel sessionModel, Pageable pageable) {
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        if (Objects.nonNull(sessionModel)) {
            builder.and(qPatrolInfo.operator.id.eq(sessionModel.getId()));
        }
        if (Objects.nonNull(request.getType())) { //巡查类型查询
            builder.and(qPatrolInfo.type.eq(request.getType()));
        }
        if (Objects.nonNull(request.getStatus())) {
            builder.and(qPatrolInfo.status.eq(request.getStatus()));
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            builder.and(qPatrolInfo.createTime.between(request.getStartTime(), request.getEndTime()));
        }
        Page<PatrolInfo> result = patrolInfoRepository.findAll(builder, pageable);
        Page<PatrolAppResponse> page = result.map(patrolInfo -> {
            PatrolAppResponse response = new PatrolAppResponse();
            cn.fintecher.gis.utils.BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            List<FileResponse> list = getPatrolFileList(patrolInfo.getId());
            List<FileResponse> imageFiles = new ArrayList<>();
            List<FileResponse> videoFiles = new ArrayList<>();
            for (FileResponse file : list) {
                if (file.getFileType().equals(PatrolFileType.IMAGE)) {
                    imageFiles.add(file);
                } else {
                    videoFiles.add(file);
                }
            }
            response.setImageFiles(imageFiles);
            response.setVideoFiles(videoFiles);
            response.setUserId(patrolInfo.getOperator().getId());
            response.setUserName(patrolInfo.getOperator().getUsername());
            Iterator<PatrolTrack> iterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId
                    .eq(patrolInfo.getId())).iterator();
            response.setPatrolTracks(Lists.newArrayList(iterator));
            return response;
        });
        return page;
    }


    /**
     * 根据id查询对应的相关信息
     *
     * @param id
     * @return
     */
    public PatrolAppResponse getByIdApp(String id) {
        PatrolAppResponse response = new PatrolAppResponse();
        patrolInfoRepository.findById(id).ifPresent(patrolInfo -> {
            cn.fintecher.gis.utils.BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            List<FileResponse> list = getPatrolFileList(patrolInfo.getId());
            List<FileResponse> imageFiles = new ArrayList<>();
            List<FileResponse> videoFiles = new ArrayList<>();
            for (FileResponse file : list) {
                if (file.getFileType().equals(PatrolFileType.IMAGE)) {
                    imageFiles.add(file);
                } else {
                    videoFiles.add(file);
                }
            }
            response.setImageFiles(imageFiles);
            response.setVideoFiles(videoFiles);
            response.setUserId(patrolInfo.getOperator().getId());
            response.setUserName(patrolInfo.getOperator().getUsername());

            Iterator<PatrolTrack> iterator = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId
                    .eq(patrolInfo.getId())).iterator();
            response.setPatrolTracks(Lists.newArrayList(iterator));
            return;
        });
        return response;
    }



    /**
     * 根据id查询对应的巡查结果信息
     */
    public PatrolFileResponse getPatrolInfoById(String id) {
        PatrolInfo patrolInfo = patrolInfoRepository.findById(id).orElseThrow(() -> new BadRequestException("", "the.patrolInfo.is.not.exist"));
        PatrolFileResponse response = new PatrolFileResponse();
        response.setContent(patrolInfo.getContent());
        List<FileResponse> list = getPatrolFileList(id);
        response.setUploadFiles(list);
        response.setId(id);
        return response;
    }

    /**
     * 根据id查询任务文件
     *
     * @param id
     * @return
     */
    public List<FileResponse> getPatrolFileList(String id) {
        List<FileResponse> list = new ArrayList<>();
        Iterable<PatrolFile> patrolFiles = patrolFileRepository.findAll(QPatrolFile.patrolFile.patrolId.eq(id));
        for (PatrolFile patrolFile : patrolFiles) {
            UploadFile uploadFile = uploadFileService.findOne(patrolFile.getFileId());
            FileResponse fileResponse = new FileResponse();
            BeanUtils.copyPropertiesIgnoreNull(uploadFile, fileResponse);
            fileResponse.setFileType(patrolFile.getFileType());
            list.add(fileResponse);
        }
        return list;
    }

    /**
     * 查询巡查结果
     */
    public List<PatrolTrack> getPatrolTrack(String id) {
        Iterable<PatrolTrack> iterable = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(id));
        return IterableUtils.toList(iterable);
    }


    /**
     * 根据巡查id查询巡查基本信息
     *
     * @param id
     * @return
     */
    public PatrolBusinessResponse getPatrolBusinessResponse(String id) {
        PatrolBusinessResponse response = new PatrolBusinessResponse();
        patrolInfoRepository.findById(id).ifPresent(patrolInfo -> {
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo, response);
            response.setUserName(patrolInfo.getOperator().getUsername());
            return;
        });
        return response;
    }

    /**
     * 添加巡查结果
     *
     * @param request
     */
    public void addPatrolResult(PatrolResultRequest request) {
        List<PatrolFile> list = new ArrayList<>();
        deletePatrolFile(request.getId());
        PatrolInfo info = new PatrolInfo();
        patrolInfoRepository.findById(request.getId()).ifPresent(patrolInfo -> {
            for (String fileId : request.getImageFileIds()) {
                PatrolFile patrolFile = new PatrolFile();
                patrolFile.setFileId(fileId);
                patrolFile.setFileType(PatrolFileType.IMAGE);
                patrolFile.setPatrolId(patrolInfo.getId());
                list.add(patrolFile);
            }
            for (String fileId : request.getVideoFileIds()) {
                PatrolFile patrolFile = new PatrolFile();
                patrolFile.setFileId(fileId);
                patrolFile.setFileType(PatrolFileType.VIDEO);
                patrolFile.setPatrolId(patrolInfo.getId());
                list.add(patrolFile);
            }
            BeanUtils.copyPropertiesIgnoreNull(patrolInfo, info);
            return;
        });
        info.setContent(request.getPatrolResult());
        patrolInfoRepository.save(info);
        patrolFileRepository.saveAll(list);
    }


    public void deletePatrolFile(String id) {
        Iterator<PatrolFile> iterator = patrolFileRepository.findAll(QPatrolFile.patrolFile.patrolId.eq(id)).iterator();
        List<PatrolFile> list = Lists.newArrayList(iterator);
        patrolFileRepository.deleteAll(list);
    }

    /**
     * 添加文件
     *
     * @param request
     */
    public void addPatrolFile(PatrolResultRequest request) {
        List<PatrolFile> list = new ArrayList<>();
        patrolInfoRepository.findById(request.getId()).ifPresent(patrolInfo -> {
            for (String fileId : request.getImageFileIds()) {
                PatrolFile patrolFile = new PatrolFile();
                patrolFile.setFileId(fileId);
                patrolFile.setFileType(PatrolFileType.IMAGE);
                patrolFile.setPatrolId(patrolInfo.getId());
                list.add(patrolFile);
            }
            for (String fileId : request.getVideoFileIds()) {
                PatrolFile patrolFile = new PatrolFile();
                patrolFile.setFileId(fileId);
                patrolFile.setFileType(PatrolFileType.VIDEO);
                patrolFile.setPatrolId(patrolInfo.getId());
                list.add(patrolFile);
            }
            return;
        });
        patrolFileRepository.saveAll(list);
    }

    /**
     * 添加对应的轨迹
     *
     * @param request
     */
    public void addTrackInfo(TrackRequest request) {
        PatrolInfo patrolInfo = patrolInfoRepository.findById(request.getPatrolId()).orElseThrow(() -> new BadRequestException("", "the.patrolInfo.is.not.exist"));
        List<PatrolTrackRequest> list = request.getPatrolTrackRequests();
        if (list == null || list.isEmpty()) {
            throw new BadRequestException("", "there.is.no.corresponding.point.information");
        }
        if (patrolInfo.getCollectData().equals(CommonShow.YES)) {
            Iterable<PatrolTrack> iterable = patrolTrackRepository.findAll(QPatrolTrack.patrolTrack.patrolId.eq(request.getPatrolId()));
            List<PatrolTrack> patrolTracks = IterableUtils.toList(iterable);
            patrolTrackRepository.deleteAll(patrolTracks);
            List<PatrolTrack> patrolTrackList = new ArrayList<>();
            for (PatrolTrackRequest patrol : list) {
                PatrolTrack patrolTrack = new PatrolTrack();
                BeanUtils.copyPropertiesIgnoreNull(patrol, patrolTrack);
                patrolTrack.setPatrolId(request.getPatrolId());//巡查任务id
                patrolTrackList.add(patrolTrack);
            }
            patrolTrackRepository.saveAll(patrolTrackList);
        }
    }


    /**
     * 结束巡查任务
     *
     * @param request
     * @return
     */
    public PatrolInfo signPatrolById(PatrolResultRequest request) {
        Optional<PatrolInfo> optional = patrolInfoRepository.findById(request.getId());
        if (!optional.isPresent()) {
            throw new BadRequestException("", "the.patrolInfo.is.not.exist");
        }
        PatrolInfo patrolInfo = optional.get();
        patrolInfo.setStatus(PatrolStatus.COMPLETE_PATROL);
        patrolInfo = patrolInfoRepository.saveAndFlush(patrolInfo);

        WebSocketMessageModel model = new WebSocketMessageModel();
        model.setContent(patrolInfo.getName() + " _任务已经巡查完成");
        model.setTitle("外业巡查");
        model.setMsgDate(new Date());
        model.setMessageType(MessageType.PATROL);
        webSocketService.sendMessage(patrolInfo.getCreateOperator().getUsername(), model);
        return patrolInfo;
    }

}
